/**
 * 
 */
package com.google.code.cisx.store.matcher;

import com.google.code.cisx.model.CommonUpdatableEntity;
import com.google.code.cisx.store.api.EntityNotFoundException;
import com.google.code.cisx.store.api.Query;
import com.google.code.cisx.store.api.Store;
import com.google.code.cisx.store.api.StoreException;

import org.hamcrest.BaseMatcher;
import org.hamcrest.Description;
import org.hamcrest.Factory;
import org.hamcrest.Matcher;
import org.junit.Assert;

/**
 * {@link Matcher} extension that provides a semantic convenience to assert if a
 * persistable JPA entity was removed from the underlying store.
 * 
 * @author <a href='mailto:rahul.thakur.xdev@gmail.com'>Rahul Thakur</a>
 * @version $Id: JpaEntity.java 258 2008-11-29 06:23:51Z rahul.thakur.xdev $
 * @since 1.0
 */
public class JpaEntity<T extends CommonUpdatableEntity, Q extends Query<T>>
    extends BaseMatcher<T> {

  /**
   * Entity to check
   */
  private T entity;

  private Class<T> klass;

  private Store<T, Q> store;

  public JpaEntity(Store<T, Q> s, Class<T> c, T t) {
    this.store = s;
    this.klass = c;
    this.entity = t;
  }

  /**
   * @{inheritDoc}
   * 
   * @see org.hamcrest.Matcher#matches(java.lang.Object)
   */

  public boolean matches(Object o) {
    Assert.assertNotNull(store);
    try {
      T obj = store.lookup(klass, entity.getId());
      return (null == obj);
    } catch (EntityNotFoundException e) {
      return true;
    } catch (StoreException e) {
      throw new RuntimeException(e);
    }
  }

  /**
   * @{inheritDoc}
   * 
   * @see org.hamcrest.SelfDescribing#describeTo(org.hamcrest.Description)
   */
  public void describeTo(Description description) {
    description.appendText("Entity is deleted");
  }

  @Factory
  public static <T extends CommonUpdatableEntity, Q extends Query<T>> Matcher<T> isDeleted(
      Store<T, Q> s, Class<T> c, T t) {
    JpaEntity<T, Q> matcher = new JpaEntity<T, Q>(s, c, t);
    return matcher;
  }

}
